/*
 *	Perlin Production Co. Ltd. September 2012 (c).
 *			agp.c
 *		Advanced Palette Generator
 */

#include "stdio.h"
#include "fdlib.h"
#include "paramlib.h"
#include "WinGDI.h"
#include "pallib.h"

#define	NUM_IP	5

#define IP_DPR  1	/* Bit deprecation input parameter index */
#define	IP_DCR	2	/* Duplicate color resolver input parameter index */
#define	NUM_DCR	3	/* Number of duplicate color resolvers */
#define	IP_FLIP	3	/* Flip palette colors */
#define	IP_DRA	4	/* Resolver attempts */

#define	FLIPDEF		1
#define	FLIPMIN		0
#define	FLIPMAX		1

INTPARM	params	[NUM_IP];
BF	bf;
BC	bc;
BI	bi;
char	inname	[0x80];
char	palname	[0x80];
char	clrname	[0x80];
RGB	rgbCLR	[0x100]; /*Vector Color Space converted to true color*/


struct _DCR	/* duplicate color resolver */
{
	char	*dcrName;
	RGB*	(*dcrResolver)(); /* pointer to duplicate color resolver */
};

#define DCR struct _DCR

DCR	dcrDCR[NUM_DCR];

InitDCR(_dcr, _name, _resolver)
DCR	*_dcr;
char	*_name;
RGB*	(*_resolver)();
{
	_dcr->dcrName		= _name;
	_dcr->dcrResolver	= _resolver;
};

	

InitOpt(_ip)
INTPARM	*_ip;
{
 DCR* dcr;
 
 dcr = dcrDCR;
	
 InitParm(_ip++, 'v', VERBMIN, VERBDEF, VERBMAX	, "verbosity");
 InitParm(_ip++, 'b', 0      , 0      , 1	, "bit deprecation");
 InitParm(_ip++, 'd', 0      , 1      , 2	, "duplicate color resolver");
 InitDCR(dcr++,"do not resolve duplicate colors"	, 0);
 InitDCR(dcr++,"resolve duplicates by closest color"	, CRCClr);
 InitDCR(dcr++,"resolve duplicates by luminosity"	, CRLumo);
 InitParm(_ip++, 'f', FLIPMIN, FLIPDEF, FLIPMAX, "flip palette");
 InitParm(_ip++, 'r', 0      , 16     , 64	, "resolver retries");
}


int main(argc,argv)
int	argc;
char	**argv;
{
	FD		*fdIn;
	FILE		*fPal;		/* buffered palette text file */
	int		verbose;
	int		attempts;
	int		isOS2;
	unsigned	size, numCol;
	RGB		*rgbBMP;
	unsigned	sizPal;
	RGB		*rgbLVL;	
	unsigned	w,h,d;
	DCR		*dcr;

	/****************************************************************/
	/* parameter initialization 					*/
	
	InitOpt(params);
	verbose	= params[IP_VERBOSE].ip_val;
	
	if (argc < 2) usage(0);
	
	if (*argv[1] == '-') trouble("Required parameter missing:","input[.BMP]");

	ExtAdd(inname , argv[1], 0x7F, ".BMP");
	ExtSub(palname, inname , 0x7F, ".PAL");
	rgbLVL = 0;
		
	if (argc == 2) ExtSub(clrname, inname, 0x7F, ".CLR");
	else
	{
		/* 3 or more parameters */
		
		if (*argv[2] == '-')
		{
			OptParm(argv, 2, argc, params, NUM_IP);
			verbose	= params[IP_VERBOSE].ip_val;
			ExtSub(clrname, inname, 0x7F, ".CLR");
		}
		else
		{
			OptParm(argv, 3, argc, params, NUM_IP);
			verbose	= params[IP_VERBOSE].ip_val;
			/* argv[2] is .CLR filename */
			rgbLVL = ~0;
			ExtAdd(clrname , argv[2], 0x7F, ".CLR");
		}
	}
	
	if (params[IP_DPR].ip_val)
	{
	  if (verbose)
	 	printf("Bit deprecation of %s colorspace conversion is enforced.\n", inname);
	 if (rgbLVL)
	 	trouble	("enforcing bit deprecation with color level file provided:"
	 		, clrname);
	 rgbLVL = 0;
	}
	else
	{
	 rgbLVL = CLR_Rd(rgbCLR, clrname, params[IP_VERBOSE].ip_val);
#if 1
	 if (!rgbLVL) exit(1);
#else
	 /*
	 if (!rgbLVL && verbose)
	 {
		printf("Switching to colorspace conversion by bit deprecation for %s", inname);
		printf(".\n");
	 }
	 */
#endif
	}
	
	dcr	= &dcrDCR[params[IP_DCR].ip_val];
	attempts= params[IP_DRA].ip_val;
	
	/* end of parameter initialization				*/
	/****************************************************************/
	
	fdIn  = InitFD(inname);
	OpenFD(fdIn, FCB_READ);
	
	if ((read(fdIn->file,&bf,sizeof(_BF))) != sizeof(_BF))
			trouble("BITMAPFILEHEADER read error in",inname);
			
	Chk64K(&bf.bfSize   , "file size");
	Chk64K(&bf.bfOffBits, "offset to pixel data");
	
	if (verbose == VERBMAX)
	{
		printf("BITMAPFILEHEADER\n");
		printf("bfSize    =%u\n",bf.bfSize);
		printf("bfOffBits =%u\n",bf.bfOffBits);
	}
			
	
	if (bf.bfType != BF_TYPE) trouble("Not a bitmap file", inname);
	
	if ((read(fdIn->file,&bc,sizeof(_BC))) != sizeof(_BC))
			trouble("BITMAPCOREHEADER read error in",inname);

	isOS2 = (bc.bcSize) == sizeof(_BC);
	
	if (verbose == VERBMAX) printf("%s bitmap\n",(isOS2 ? "OS/2" : "Windows"));
	
	if (isOS2)
	{
		putBC(&bc, verbose);
		numCol	= 1 << bc.bcBitCount;

		w = bc.bcWidth;
		h = bc.bcHeight;
		d = bc.bcBitCount;
	}
	else
	{
		movmem(&bc, &bi, sizeof(_BC));
		
		Chk64K(&bi.biSize, "header size");
		
		size = bc.bcSize - sizeof(_BC);
		
		if ((read(fdIn->file, &bi.biPlanes,size)) != size)
				trouble("BITMAPINFOHEADER read error in",inname);
				
		putBI(&bi, verbose);
		numCol	= 1 << bi.biBitCount;
		
		w = bi.biWidth;
		h = bi.biHeight;
		d = bi.biBitCount;
	}	

	/*skip = bf.bfOffBits - bc.bcSize - sizeof(_BF);*/
	sizPal = numCol * sizeof(_RGB);
	
	/* sizPal != 0x10 */
	
	if (!(rgbBMP = malloc(sizPal)))
		trouble("allocate bitmap palette memory for",inname);
		
	if (verbose) printf("Reading %s bitmap palette\n", inname);
		
	if ((read(fdIn->file, rgbBMP, sizPal)) != sizPal)
		trouble("read bitmap palette from",inname);

	FreeFD(fdIn);
	
	if (verbose == VERBMAX) printf("Resolver: %s\n",dcr->dcrName);
	
	if (params[IP_FLIP].ip_val)
	{
		if (verbose) printf("Flipping palette\n");
		PalFli	(rgbBMP);
	}
	PalWrt(palname, rgbBMP, rgbLVL, dcr->dcrResolver, attempts, verbose);
	
	free(rgbBMP);
	return 	0;
}




usage(_text)
char* _text;
{
 int	i;
 DCR	*dcr;

 printf("Perlin Production Co. Ltd. April 2014\n");
 printf("*** ADVANCED PALETTE GENERATOR ***, ver. 1.2\n");
 printf("Generates Vector-06c palette .PAL file from .BMP image\n");
 printf("\nTo display BMP image on Vector-06c, do the following:\n");
 printf("1. Use IDC utility to convert .BMP image into Vector-06c .BIN format.\n");
 printf("2. Use CLR utility to generate colorspace component levels .CLR file.\n");
 rev_vid();
 printf("3. Use APG (this program) to get image palette from .BMP and .CLR files.\n");
 nrm_vid();
 printf("4. Use SHIM image viewer to display .BIN image in .PAL palette.\n");
 printf("If color level file is not found, APG will convert input .BMP\n");
 printf("colorspace to 233 Vector-06c color space using bit deprecation.\n");
 printf("Usage:\n");
 rev_vid();
 printf("APG input[.BMP] [input[.CLR]] [options]\n");
 nrm_vid();
 printf("-- Optional Parameters:\n");
 printf("[-v[%d]] - verbosity level %d-%d\n", VERBDEF, VERBMIN, VERBMAX);
 printf("[-b[%d]] - bit-deprecated colorspace conversion %d-%d\n", 0, 0, 1);
 printf("[-f[%d]] - flip palette colors %d-%d\n", FLIPDEF,FLIPMIN,FLIPMAX);
 printf("[-d[%d]] - duplicate color resolver %d-%d:\n", 1, 0, 2);
 
 for (i=0, dcr = dcrDCR; i < NUM_DCR; ++i, ++dcr)
 {
 	printf("\t-d%d : %s\n",i,dcr->dcrName);
 }
 printf("[-r[%d]] - resolver retries %d-%d\n", 16, 0, 64);
 
 if (_text) trouble(_text, 0);
 else exit(0);
}
